﻿// owner 蒋家伟

#pragma once
#include "IClassFieldDescriptor.h"

namespace jsdk
{
    class CommonFieldDescriptrImp;
    // 类别描述 : 字段描述符的公共内容
    class DATASCHEMA_EXPORT CommonFieldDescriptor : public IClassFieldDescriptor
    {
    public:
        /// \ 获取s_pClassUid_Key 对应的uid
        static bool getClassUidFromJsonObject(const JsonObject& jsonObject, jsdk::UniqueId& uid);

        /// \ 获取错误信息的通用前缀
        std::wstring getErrorMsgPrefix() const;

    protected:
        /// \ 容器使用的字段描述
        static const char* s_pClassUid_Key;            // 支持序列化的自定义类型才需要写入Uid

        /// \ brief 创建类别字段描述符
        /// \ in variableName     变量名称
        /// \ in v_offset         变量相对偏移
        /// \ in v_typeName       变量类别名称
        /// \ in v_typeHashCode   变量类别名称对应的hashcode
        /// \ in v_typeUid        变量类别名称唯一uid，取决于是否定义
        CommonFieldDescriptor(
            const std::wstring& variableName,
            uint64_t v_offset,
            size_t v_typeHashCode,
            const std::wstring& v_typeName);
        virtual ~CommonFieldDescriptor();

        /// \ breif 序列化对象的值
        /// \ in object 用于存放当前对象的jsonObject
        /// \ out 错误信息
        /// \ return true 表示序列化成功
        virtual bool serializeValue(JsonDocument& jsonDoc, JsonObject& jsonObject) const = 0;

        /// \ breif 反序列化对象的值
        /// \ in object 用于存放当前对象的jsonObject
        /// \ out 错误信息
        /// \ return true 表示反序列化成功
        virtual bool unserializeValue(const JsonObject& jsonObject) = 0;

        /// \ brief 默认实现，什么也没做
        /// \ 如果当前描述符是 ownerptr则需要实现，否则不用实现
        virtual jsdk::OwnerPtr<DBSchemaObject> getCastDBSchemaObject(jsdk::OwnerPtr<DBSchemaObject> opSourceDBSchemaObject) const noexcept override;

        /// \ 与getCastDBSchemaObject相匹配的静态实现
        template<typename T>
        static jsdk::OwnerPtr<DBSchemaObject> castDBSchemaObject(jsdk::OwnerPtr<DBSchemaObject> opSourceDBSchemaObject)
        {
            if (opSourceDBSchemaObject == nullptr)
                return nullptr;
            DBSchemaObject * pDBSchemaObject = (DBSchemaObject*)(quick_cast<T>(opSourceDBSchemaObject.release()));
            opSourceDBSchemaObject.reset(pDBSchemaObject);
            return transformOwnerShip(opSourceDBSchemaObject);
        }

    private:
        // 继承IClassFieldDescriptor
        virtual const std::wstring& getVariableName() const noexcept override final;
        virtual const std::wstring& getTypeName() const noexcept override final;
        virtual const std::size_t& getTypeHashCode() const noexcept override final;
        virtual const void* getFiledAddress() const noexcept override final;
        virtual void* getFiledAddress() noexcept override final;
        virtual bool serialize(JsonDocument& jsonDoc, JsonObject& jsonObject) const noexcept override final;
        virtual bool unserialize(const JsonObject& jsonObject) noexcept override final;
        virtual void setClassAddress(void* pClassAddress) noexcept override final;
        virtual void setOwnerClassNameAndUid(const std::wstring& className, const jsdk::UniqueId& uid) noexcept override final;

        // owner
        const uint64_t& getOffset() const;
        const std::size_t& getSerializetypeHashCode() const;
    public:

        /// \ brief 将value与uidstr组合到jsonObject中
        /// \ note : 此方法为内部方法，外部无需调用
        static bool schemaObjectSerialize(JsonDocument& jsonDoc, JsonObject& jsonObject, const jsdk::UniqueId& typeUid, JsonObject&& jsonObjectValue);

        /// \ brief 虽然变量是静态public，但是不期望其他工程可以使用
        /// \ breif 用于存储的值对应的json : Key
        static const char* s_pValue_Key;

    private:
        CommonFieldDescriptrImp* m_pCommonFieldDescriptrImp = nullptr;
    };
}
